package handler

import (
	"entrytask/facade"
	"entrytask/model"
	"entrytask/pkg/error"
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"strconv"
	"time"
)

// LoginUser 用户登陆
func LoginUser(c *gin.Context) {
	start := time.Now().UnixNano()
	defer consumeTime(start, facade.Login)

	// 表单参数校验
	username := c.PostForm("username")
	password := c.PostForm("password")
	if username == "" || password == "" {
		SendResponse(c, errno.ErrValidation, nil)
		return
	}

	//log.Printf("user[%s:%s] login success!", username, password)
	//middleware.RPCCall(facade.Login, &facade.UserLogin)
	//main.RPCPooledCall(facade.Login, &facade.UserLogin)

	user, token, err := facade.UserLogin(&facade.UserLoginRequest{
		Username: username,
		Password: password,
	})

	log.Println("response name from rpc: ", token)

	SendResponseWithCookie(c, token, err, user)
}

// UpdateUser 用户信息更新
func UpdateUser(c *gin.Context) {

	start := time.Now().UnixNano()
	defer consumeTime(start, facade.UpdateUser)

	user, errRes := getUserByToken(c)
	// 未登陆友好响应
	if errRes != nil && errRes.Error() != errno.OK.Error() {
		SendResponse(c, errRes, nil)
		return
	}

	username := user.Username          // 定位唯一用户 todo 跟token比对
	nickname := c.PostForm("nickname") // 获取用户变更的nickname

	// 头像文件上传, filePath: 头像上传路径
	file, err := c.FormFile("profile")
	filePath := ""
	if err == nil {
		// 简单带上时间戳生成随机串拼接，防止重名
		filePath = fmt.Sprint("./static/pic/", strconv.FormatInt(time.Now().UnixNano(), 10)+"_"+file.Filename)
		err = c.SaveUploadedFile(file, filePath)
		if err != nil {
			log.Println("file upload fail, ", err)
			SendResponse(c, err, nil)
			return
		}
	}

	// calling for update user info including nickname and pic file path
	//middleware.RPCCall(facade.UpdateUser, &facade.UserUpdateInfo)
	//main.RPCPooledCall(facade.UpdateUser, &facade.UserUpdateInfo)

	user, err = facade.UserUpdateInfo(&facade.UserUpdateRequest{
		Username:    username,
		Nickname:    nickname,
		ProfilePath: filePath,
	})

	log.Println("user update success! user info: ", user)

	//SendResponse(c)
	SendResponseRedirect(c)
}

// AddUser 增加用户
func AddUser(c *gin.Context) {
	var req model.User
	if err := c.Bind(&req); err != nil {
		SendResponse(c, errno.ErrBind, nil)
		return
	}
	user := model.User{
		Username: req.Username,
		Password: req.Password,
		Nickname: req.Nickname,
	}
	// Validate the data.
	if err := user.Validate(); err != nil {
		SendResponse(c, errno.ErrValidation, nil)
		return
	}
	// rpc call for Insert the user to the database.
	//if _, err := user.Create(); err != nil {
	//	SendResponse(c, errno.ErrDatabase, nil)
	//	return
	//}
	// Show the user information.
	SendResponse(c, nil, user)
}

// QueryUserByName 查询用户
func QueryUserByName(c *gin.Context) {

	start := time.Now().UnixNano()
	defer consumeTime(start, facade.QueryName)

	name := c.Query("username")
	if name == "" {
		SendResponse(c, errno.ErrValidation, nil)
		return
	}

	//middleware.RPCCall(facade.QueryName, &facade.UserQueryByName)
	//main.RPCPooledCall(facade.QueryName, &facade.UserQueryByName)

	user, err := facade.UserQueryByName(name)
	if err != nil && err.Error() != errno.OK.Error() {
		SendResponse(c, err, nil)
		return
	}

	SendResponse(c, err, user)
}

// QueryUserByToken 查询用户
func QueryUserByToken(c *gin.Context) {

	start := time.Now().UnixNano()
	defer consumeTime(start, facade.QueryToken)

	user, err := getUserByToken(c)

	// todo 未登陆友好响应
	if err != nil && err.Error() != errno.OK.Error() {
		SendResponse(c, err, nil)
		return
	}

	SendResponse(c, err, user)
}

func consumeTime(start int64, method string) {
	end := time.Now().UnixNano()
	log.Printf("api server method[%s] consume time: %d ns", method, end-start)
}

func getUserByToken(c *gin.Context) (*facade.User, *errno.Errno) {

	token, err := c.Cookie("token")
	if err != nil || token == "" {
		return nil, errno.ErrUserNotFound
	}

	//middleware.RPCCall(facade.QueryToken, &facade.UserQueryByToken)
	//main.RPCPooledCall(facade.QueryToken, &facade.UserQueryByToken)

	user, errs := facade.UserQueryByToken(token)

	return user, errs
}

// saveImg 文件上传
/*func saveImg(img multipart.File, name string) {
	file, err := os.Create(fmt.Sprintf("./static/pic/%s", name))
	defer func(file *os.File) {
		err := file.Close()
		if err != nil {
			log.Println(err.Error())
		}
	}(file)

	if err != nil {
		log.Println(err.Error())
		return
	}
	_, err = io.Copy(file, img)
	if err != nil {
		log.Println(err.Error())
		return
	}
}*/
